package com.example.utils;

import com.example.config.WxpayConfig;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.UUID;

/**
 * @author 也是
 * @Date 2023/3/29
 */
public class WeixinchatPayUtils {
	public static String getNonceStr() {
		return UUID.randomUUID().toString()
				.replaceAll("-", "")
				.substring(0, 32);
	}

	/**
	 * 参考网站 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_4.shtml
	 * 计算签名值
	 *
	 * @param appId
	 * @param prepay_id
	 * @return
	 * @throws IOException
	 * @throws SignatureException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 */
	public static HashMap<String, Object> getTokenJSAPI(String appId, String prepay_id) throws Exception {
		// 获取随机字符串
		String nonceStr = getNonceStr();
		// 获取微信小程序支付package
		String packagestr = "prepay_id=" + prepay_id;
		long timestamp = System.currentTimeMillis() / 1000;
		//签名，使用字段appId、timeStamp、nonceStr、package计算得出的签名值
		String message = buildMessageTwo(appId, timestamp, nonceStr, packagestr);
		//获取对应的签名
		String signature = sign(message.getBytes("utf-8"));
		// 组装返回
		HashMap<String, Object> map = new HashMap<>();
		map.put("appId", appId);
		map.put("timeStamp", String.valueOf(timestamp));
		map.put("nonceStr", nonceStr);
		map.put("package", packagestr);
		map.put("signType", "RSA");
		map.put("paySign", signature);
		return map;
	}



	/**
	 * 参考网站 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_4.shtml
	 * 计算签名值
	 * @param appId
	 * @param prepay_id
	 * @return
	 * @throws IOException
	 * @throws SignatureException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 */
	public static HashMap<String, Object> getTokenApp(String appId, String prepay_id) throws Exception {
		// 获取随机字符串
		String nonceStr = getNonceStr();
		// 获取微信小程序支付package
		long timestamp = System.currentTimeMillis() / 1000;
		//签名，使用字段appId、timeStamp、nonceStr、package计算得出的签名值
		String message = buildMessageTwo(appId, timestamp, nonceStr, prepay_id);
		//
		String signature = sign(message.getBytes("utf-8"));
		// 组装返回
		HashMap<String, Object> map = new HashMap<>();
		map.put("appId", appId);
		map.put("partnerid", WxpayConfig.mch_id);
		map.put("prepayid", prepay_id);
		map.put("package", "Sign=WXPay");
		map.put("nonceStr", nonceStr);
		map.put("timeStamp", String.valueOf(timestamp));
		map.put("sign", signature);
		return map;
	}
	/**
	 * 生成签名
	 *
	 * @param message
	 * @return
	 * @throws Exception
	 */
	public static String sign(byte[] message) throws Exception {
		Signature sign = Signature.getInstance("SHA256withRSA");
		sign.initSign(getPrivateKey(WxpayConfig.KeyPath));
		sign.update(message);
		return Base64.getEncoder().encodeToString(sign.sign());
	}

	/**
	 * 获取私钥
	 * @param filename 私钥文件路径  (required)
	 * @return 私钥对象
	 */
	public static PrivateKey getPrivateKey(String filename) throws IOException {
		System.out.println("filename:" + filename);
		String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
		try {
			String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
					.replace("-----END PRIVATE KEY-----", "")
					.replaceAll("\\s+", "");

			KeyFactory kf = KeyFactory.getInstance("RSA");
			return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("当前Java环境不支持RSA", e);
		} catch (InvalidKeySpecException e) {
			throw new RuntimeException("无效的密钥格式");
		}
	}
	/**
	 * 拼接参数
	 *
	 * @return
	 */

	private static String buildMessageTwo(String appId, long timestamp, String nonceStr, String packag) {
		return appId + "\n"
				+ timestamp + "\n"
				+ nonceStr + "\n"
				+ packag + "\n";
	}
}
